﻿using AutoMapper;
using Core.SimpleTemp.Common;
using Core.SimpleTemp.Common.PagingQuery;
using Core.Toolkit.AutoMapperExtend.DataDictionary;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Core.Toolkit.Core.Application
{
    public class CoreMapper
    {

        
        public static string assemblyNames = "Core.SimpleTemp.Application;Core.Toolkit";
        public static void Initialize(IDataDicPool dataDicPool )
        {
            Mapper.Initialize(cfg =>
            {
                RegistryMapper(cfg, dataDicPool);

                cfg.ValidateInlineMaps = false;
                cfg.CreateMap(typeof(LoadPageOffsetModel<,>), typeof(PagingModel<>));
                cfg.CreateMap(typeof(PagingModel<>), typeof(LoadPageOffsetModel<,>));
                cfg.CreateMap(typeof(LoadPageOffsetModelAuto<,>), typeof(PagingModel<>));
                cfg.CreateMap(typeof(PagingModel<>), typeof(LoadPageOffsetModelAuto<,>));
            });

        }



        public static void RegistryMapper(IMapperConfigurationExpression cfg, IDataDicPool dataDicPool)
        {
            if (!String.IsNullOrEmpty(assemblyNames))
            {
                var arrAssemb = assemblyNames.Split(';');
                //循环程序集
                foreach (var assemblyName in arrAssemb)
                {
                    Assembly assembly = Assembly.Load(assemblyName);
                    List<Type> ts = assembly.GetTypes().ToList();
                    var dtos = ts.Where(s => s.GetCustomAttributes<CreateMapAttribute>() != null && s.GetCustomAttributes<CreateMapAttribute>().Any());
                    //循环每个程序程序集里面的CreateMapAttribute标签对象
                    foreach (var dtoItem in dtos)
                    {
                        var createMapAttributeList = dtoItem.GetCustomAttributes<CreateMapAttribute>();
                        //注册ClassMaping规则
                        foreach (var createMapAttribute in createMapAttributeList)
                        {
                            if (createMapAttribute != null)
                            {
                                //
                                var mappingExpression = cfg.CreateMap(createMapAttribute.SourceType, dtoItem);
                                //注册MMapping转换规则
                                RegistryDataDicConvert(ref mappingExpression, dtoItem, createMapAttribute.SourceType, dataDicPool);
                            }
                        }

                    }
                }
            }
        }


        /// <summary>
        /// 注册转换规则
        /// </summary>
        /// <param name="mappingExpression"></param>
        /// <param name="dtoType"></param>
        /// <param name="entity"></param>
        /// <param name="dataDicPool"></param>
        /// <param name="concurrentDataDicPool"></param>
        public static void RegistryDataDicConvert(ref IMappingExpression mappingExpression, Type dtoType, Type entity, IDataDicPool dataDicPool)
        {
            var properties = dtoType.GetProperties().Where(p => p.GetCustomAttribute<KeyToValueAttribute>() != null);
            foreach (var propertieItem in properties)
            {
                Registry(ref mappingExpression, propertieItem, dataDicPool, entity);
                
            }
            properties = dtoType.GetProperties().Where(p => p.GetCustomAttribute<ConcurrentKeyToValueAttribute>() != null);
            foreach (var propertieItem in properties)
            {
                RegistryForConcurrentD(ref mappingExpression, propertieItem, entity);
            }
        }

        /// <summary>
        /// 注册Mapp转换规则
        /// 注册后从非安全池中取数据
        /// </summary>
        /// <param name="mappingExpression"></param>
        /// <param name="propertieItem"></param>
        /// <param name="dataDicPool"></param>
        /// <param name="entity"></param>
        public static void Registry(ref IMappingExpression mappingExpression, PropertyInfo propertieItem, IDataDicPool dataDicPool, Type entity)
        {
            PropertyInfo entityPropertie = null;
            var keyToValue = propertieItem.GetCustomAttribute<KeyToValueAttribute>();
            if (keyToValue == null)
                return;
            if (string.IsNullOrWhiteSpace(keyToValue.KeyPropertyName))
                entityPropertie = entity.GetProperties().Where(a => a.Name == propertieItem.Name).FirstOrDefault();
            else
                entityPropertie = entity.GetProperties().Where(a => a.Name == keyToValue.KeyPropertyName).FirstOrDefault();
            mappingExpression.ForMember(propertieItem.Name, opt =>
            {
                var keyToValueAttribute = propertieItem.GetCustomAttribute<KeyToValueAttribute>();
                opt.MapFrom(s =>
                     dataDicPool.GetDicValue(
                        keyToValueAttribute.Category,
                        entityPropertie.GetValue(s).ToString()
                        )
                );
            });
        }

        /// <summary>
        /// 注册Mapp转换规则
        /// 注册后从安全池中取数据
        /// </summary>
        /// <param name="mappingExpression"></param>
        /// <param name="propertieItem"></param>
        /// <param name="concurrentDataDicPool"></param>
        /// <param name="entity"></param>
        public static void RegistryForConcurrentD(ref IMappingExpression mappingExpression, PropertyInfo propertieItem, Type entity)
        {
            PropertyInfo entityPropertie = null;
            var keyToValue = propertieItem.GetCustomAttribute<ConcurrentKeyToValueAttribute>();
            if (keyToValue == null)
                return;
            if (string.IsNullOrWhiteSpace(keyToValue.KeyPropertyName))
                entityPropertie = entity.GetProperties().Where(a => a.Name == propertieItem.Name).FirstOrDefault();
            else
                entityPropertie = entity.GetProperties().Where(a => a.Name == keyToValue.KeyPropertyName).FirstOrDefault();
            mappingExpression.ForMember(propertieItem.Name, opt =>
            {
                var keyToValueAttribute = propertieItem.GetCustomAttribute<ConcurrentKeyToValueAttribute>();
                opt.MapFrom(s =>
                     ConcurrentDataDicPool.GetDicValue(
                        keyToValueAttribute.Category,
                        entityPropertie.GetValue(s).ToString()
                        )
                );
            });
        }
    }
}
